package com.job.search.service.impl;

import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch._types.query_dsl.Operator;
import co.elastic.clients.elasticsearch.core.DeleteResponse;
import co.elastic.clients.elasticsearch.core.GetResponse;
import co.elastic.clients.elasticsearch.core.SearchResponse;
import co.elastic.clients.elasticsearch.core.UpdateResponse;
import co.elastic.clients.elasticsearch.core.bulk.BulkOperation;
import co.elastic.clients.elasticsearch.core.search.Hit;
import com.job.client.common.result.AppHttpCode;
import com.job.client.common.result.ResponseResult;
import com.job.client.model.company.dto.CompanyEsDto;
import com.job.client.model.company.pojo.Company;
import com.job.client.model.posts.dto.PostsEsDto;
import com.job.client.model.posts.pojo.Posts;
import com.job.search.constant.EsIndexConstant;
import com.job.search.constant.PageSearchConstant;
import com.job.search.dto.PostsSearchDto;
import com.job.search.service.SearchCompanyService;
import com.job.search.service.SearchPostsService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

@Service
@Slf4j
public class SearchPostsServiceImpl implements SearchPostsService {
    @Autowired
    private ElasticsearchClient client;
    @Override
    public ResponseResult addPosts(PostsEsDto posts) {
        if(posts==null || posts.getCompanyId()==null){
            return ResponseResult.ErrorResult(AppHttpCode.DATA_NULL);
        }
        try {
            client.index(i->i.index(EsIndexConstant.INDEX_POSTS).id(posts.getPostsId()).document(posts));
        } catch (IOException e) {
            log.error("保存posts的document出错:"+e.getMessage());
            e.printStackTrace();
            return ResponseResult.ErrorResult(AppHttpCode.SERVICE_ERROR);
        }
        return ResponseResult.OkResult();
    }

    @Override
    public ResponseResult getById(String postsId) {
        if(postsId==null){
            return ResponseResult.ErrorResult(AppHttpCode.DATA_NULL);
        }
        GetResponse<PostsEsDto> getResponse=null;
        try {
            getResponse = client.get(g -> g.index(EsIndexConstant.INDEX_POSTS).id(postsId), PostsEsDto.class);
        } catch (IOException e) {
            log.error("查找posts出错:"+e.getMessage());
            e.printStackTrace();
            return ResponseResult.ErrorResult(AppHttpCode.SERVICE_ERROR);
        }
        return ResponseResult.OkResult(getResponse.source());
    }

    @Override
    public ResponseResult blkAddPosts(List<PostsEsDto> postsEsDtoList) {
        List<BulkOperation> bulkOperationArrayList = new ArrayList<>();
        //遍历添加到bulk中
        for(PostsEsDto posts : postsEsDtoList){
            bulkOperationArrayList.add(BulkOperation.of(o->o.index(i->i.document(posts))));
        }
        try {
            client.bulk(b -> b.index(EsIndexConstant.INDEX_POSTS)
                    .operations(bulkOperationArrayList));
        } catch (IOException e) {
            log.error("批量保存POSTS的数据时出错:"+e.getMessage());
            throw new RuntimeException(e);
        }
        return ResponseResult.OkResult();
    }

    @Override
    public ResponseResult deleteById(String postsId) {
        if(postsId == null){
            return ResponseResult.ErrorResult(AppHttpCode.DATA_NULL);
        }
        DeleteResponse deleteResponse = null;
        try {
            deleteResponse = client.delete(g -> g.index(EsIndexConstant.INDEX_POSTS).id(postsId));
        } catch (IOException e) {
            log.error("删除 POSTS 出错：" + e.getMessage());
            e.printStackTrace();
            return ResponseResult.ErrorResult(AppHttpCode.SERVICE_ERROR);
        }
        boolean flag = deleteResponse.result().jsonValue().equals("Deleted");
        if(flag){
            return ResponseResult.OkResult();
        }
        return ResponseResult.ErrorResult(AppHttpCode.SERVICE_ERROR);
    }

    @Override
    public ResponseResult modifyPartialById(PostsEsDto posts) {
        if(posts==null || posts.getPostsId()==null){
            return ResponseResult.ErrorResult(AppHttpCode.DATA_NULL);
        }
        UpdateResponse<PostsEsDto> updateResponse = null;
        try {
            updateResponse = client.update(u -> u
                            .index(EsIndexConstant.INDEX_POSTS)
                            .id(posts.getPostsId())
                            .doc(posts)
                    , PostsEsDto.class);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        boolean flag = updateResponse.result().jsonValue().equals("updated");
        if(flag){
            return ResponseResult.OkResult();
        }
        return ResponseResult.ErrorResult(AppHttpCode.SERVICE_ERROR);
    }

    @Override
    public ResponseResult search(PostsSearchDto dto) {
        if(dto==null){
            return ResponseResult.ErrorResult(AppHttpCode.DATA_NULL);
        }

        SearchResponse<PostsEsDto> search = null;
        try {
            if(! ("".equals(dto.getName())) && "".equals(dto.getCity())){
                search = client.search(s -> s
                                .index(EsIndexConstant.INDEX_POSTS)
                                .query(q -> q
                                        .match(t -> t
                                                .field("name")
                                                .query(v -> v.stringValue(dto.getName()))
                                        ))
                                .from(PageSearchConstant.FROM)
                                .size(PageSearchConstant.SIZE)
                        , PostsEsDto.class);
            }else if(! ("".equals(dto.getCity())) && "".equals(dto.getName())){
                search = client.search(s -> s
                                .index(EsIndexConstant.INDEX_POSTS)
                                //查询name字段包含hello的document(不使用分词器精确查找)
                                .query(q -> q
                                        .term(t -> t
                                                .field("city")
                                                .value(v -> v.stringValue(dto.getCity()))
                                        ))
                                //分页查询，从第0页开始查询3个document
                                .from(PageSearchConstant.FROM)
                                .size(PageSearchConstant.SIZE)
                        , PostsEsDto.class);
            }else if(!("".equals(dto.getCity())) && !("".equals(dto.getName()))) {
                System.out.println("进入");
                search = client.search(s -> s
                                .index(EsIndexConstant.INDEX_POSTS)
                                .query(q -> q
                                        .term(t -> t
                                                .field("city")
                                                .value(v -> v.stringValue(dto.getCity()))
                                        ))
                                .query(q -> q
                                        .match(t -> t
                                                .field("name")
                                                .query(v -> v.stringValue(dto.getName()))
                                        ))

                        , PostsEsDto.class);
            }else{
                search = client.search(s -> s
                                .index(EsIndexConstant.INDEX_POSTS)
                                .from(PageSearchConstant.FROM)
                                .size(PageSearchConstant.SIZE)
                        , PostsEsDto.class);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        List<PostsEsDto> list = new ArrayList<>();
        for (Hit<PostsEsDto> hit : search.hits().hits()) {
            list.add(hit.source());
        }
        return ResponseResult.OkResult(list);
    }

    @Override
    public ResponseResult searchHighlight(PostsSearchDto dto) {
        if(dto==null){
            return ResponseResult.ErrorResult(AppHttpCode.DATA_NULL);
        }

        SearchResponse<PostsEsDto> search = null;
        try {
            if(! ("".equals(dto.getName())) && "".equals(dto.getCity())){
                search = client.search(s -> s
                                .index(EsIndexConstant.INDEX_POSTS)
                                .query(q -> q
                                        .match(t -> t
                                                .field("name")
                                                .query(v -> v.stringValue(dto.getName()))
                                        ))
                                .highlight(highlightBuilder -> highlightBuilder
                                        .preTags("<font color='#00BEBD'>")
                                        .postTags("</font>")
                                        .requireFieldMatch(true) //多字段时，需要设置为false
                                        .fields("name", highlightFieldBuilder -> highlightFieldBuilder)
                                )
                                .from(PageSearchConstant.FROM)
                                .size(PageSearchConstant.SIZE)
                        , PostsEsDto.class);
            }else if(! ("".equals(dto.getCity())) && "".equals(dto.getName())){
                search = client.search(s -> s
                                .index(EsIndexConstant.INDEX_POSTS)
                                //查询name字段包含hello的document(不使用分词器精确查找)
                                .query(q -> q
                                        .match(t -> t
                                                .field("city")
                                                .query(v -> v.stringValue(dto.getCity()))
                                        ))
                                .highlight(highlightBuilder -> highlightBuilder
                                        .preTags("<font color='#00BEBD'>")
                                        .postTags("</font>")
                                        .requireFieldMatch(true) //多字段时，需要设置为false
                                        .fields("city", highlightFieldBuilder -> highlightFieldBuilder)
                                )
                                //分页查询，从第0页开始查询3个document
                                .from(PageSearchConstant.FROM)
                                .size(PageSearchConstant.SIZE)
                        , PostsEsDto.class);
            }else if(!("".equals(dto.getCity())) && !("".equals(dto.getName()))) {
                search = client.search(s -> s
                                .index(EsIndexConstant.INDEX_POSTS)
                                .query(q -> q
                                        .match(t -> t
                                                .field("name")
                                                .query(v -> v.stringValue(dto.getName()))
                                        ))
                                .query(q -> q
                                        .match(t -> t
                                                .field("city")
                                                .query(v -> v.stringValue(dto.getCity()))
                                        ))
                                .highlight(highlightBuilder -> highlightBuilder
                                        .preTags("<font color='#00BEBD'>")
                                        .postTags("</font>")
                                        .requireFieldMatch(false) //多字段时，需要设置为false
                                        .fields("name", highlightFieldBuilder -> highlightFieldBuilder)
                                        .fields("city",highlightFieldBuilder -> highlightFieldBuilder)
                                )
                                //分页查询，从第0页开始查询3个document
                                .from(PageSearchConstant.FROM)
                                .size(PageSearchConstant.SIZE)
                        , PostsEsDto.class);
            }else{
                search = client.search(s -> s
                                .index(EsIndexConstant.INDEX_POSTS)
                                .from(PageSearchConstant.FROM)
                                .size(PageSearchConstant.SIZE)
                        , PostsEsDto.class);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        List<List<String>> list = new ArrayList<>();
        for (Hit<PostsEsDto> hit : search.hits().hits()) {
            if(hit.highlight().get("name")!=null){
                list.add(Arrays.asList(hit.highlight().get("name").get(0),hit.source().getName()));
            }
            if(hit.highlight().get("city")!=null){
                list.add(Arrays.asList(hit.highlight().get("city").get(0),hit.source().getCity()));
            }
        }
        return ResponseResult.OkResult(list);
    }
}
